/**
 * @file JSONArray.cpp
 */
#include "JSONNode.h"
#include "../common/UtilFuncT.h"
#include "../common/CppMemPool.h"
#include "../lang/Primitive.h"
#include "JSONException.h"

using namespace cppflib::collections;
using namespace cppflib::collections::tree;
using namespace cppflib::lang;

namespace cppflib
{

namespace json
{

JSONArray::JSONArray(void)
{
   pValList = new ListCppObjT<BaseObject>();
   cppmempool::Retain(pValList);
}

JSONArray::~JSONArray(void)
{
   cppmempool::Release(pValList);
}

JSONNode::nodetype_t JSONArray::GetNodeType()
{
   return JSONNode::JN_ARRAY;
}

JSONObject * JSONArray::CastToJSONObject()
{
   throw JSONException(_S("This is not a JSONObject"));
}

JSONArray * JSONArray::CastToJSONArray()
{
   return this;
}

JSONNode::valuetype_t JSONArray::GetValueType(u32_t index)
{
   return JSONNode::GetValueType(this->Get(index));
}

BaseObject * JSONArray::Get(u32_t index)
{
   if (index >= pValList->GetCount())
      throw JSONException(_S("Index is greater than or equal to number of values"));
   return pValList->Get(static_cast<int>(index));
}

sz_t JSONArray::GetNumberOfValues()
{
   return pValList->GetCount();
}

CFString * JSONArray::GetString(u32_t index)
{
   BaseObject *pVal = Get(index);
   if (!cppflib::InstanceOf<CFString>(pVal))
      throw JSONException(_S("Value is not a string"));
   return static_cast<CFString*>(pVal);
}

bool JSONArray::GetBoolean(u32_t index)
{
   BaseObject *pVal = Get(index);
   if (!cppflib::InstanceOf<Boolean>(pVal))
      throw JSONException(_S("Value is not a boolean"));
   return static_cast<Boolean*>(pVal)->Value();
}

double JSONArray::GetDouble(u32_t index)
{
   BaseObject *pVal = Get(index);
   if (!cppflib::InstanceOf<Double>(pVal))
      throw JSONException(_S("Value is not a double"));
   return static_cast<Double*>(pVal)->Value();
}

int JSONArray::GetInt32(u32_t index)
{
   BaseObject *pVal = Get(index);
   if (!cppflib::InstanceOf<Int32>(pVal))
      throw JSONException(_S("Value is not a 32 bit integer"));
   return static_cast<Int32*>(pVal)->Value();
}

i64_t JSONArray::GetInt64(u32_t index)
{
   BaseObject *pVal = Get(index);
   if (cppflib::InstanceOf<Int64>(pVal)) 
      return static_cast<Int64*>(pVal)->Value();
   else if (cppflib::InstanceOf<Int32>(pVal))
      return static_cast<Int32*>(pVal)->Value();
   
   throw JSONException(_S("Value is not an integer"));
}

JSONObject * JSONArray::GetJSONObject(u32_t index)
{
   BaseObject *pVal = Get(index);
   if (!cppflib::InstanceOf<JSONObject>(pVal))
      throw JSONException(_S("Value is not a JSONObject"));
   return static_cast<JSONObject*>(pVal);
}

JSONArray * JSONArray::GetJSONArray(u32_t index)
{
   BaseObject *pVal = Get(index);
   if (!cppflib::InstanceOf<JSONArray>(pVal))
      throw JSONException(_S("Value is not a JSONArray"));
   return static_cast<JSONArray*>(pVal);
}

bool JSONArray::IsNull(u32_t index)
{
   return (GetValueType(index) == JSONNode::JVL_NULL);
}

void JSONArray::Append(CFString *pVal)
{
   if (!pVal) throw JSONException(_S("string cannot be NULL"));
   pValList->AddTail(pVal);
}

void JSONArray::Append(bool val)
{
   pValList->AddTail(new Boolean(val));
}

void JSONArray::Append(double val)
{
   pValList->AddTail(new Double(val));
}

void JSONArray::Append(int val)
{
   pValList->AddTail(new Int32(val));
}

void JSONArray::Append(i64_t val)
{
   pValList->AddTail(new Int64(val));
}

/**
 *  Append a JSONObject as value and will automatically set it as a child of this JSONArray.
 */
void JSONArray::Append(JSONObject *pJObj)
{
   if (!pJObj) throw JSONException(_S("JSONObject cannot be NULL"));
   pValList->AddTail(pJObj);
   this->AddChild(pJObj);
}

/**
 *  Append a JSONArray as value and will automatically set it as a child of this JSONArray.
 */
void JSONArray::Append(JSONArray *pJArray)
{
   if (!pJArray) throw JSONException(_S("JSONArray cannot be NULL"));
   pValList->AddTail(pJArray);
   this->AddChild(pJArray);
}

void JSONArray::AppendNull()
{
   pValList->AddTail(NULL);
}

bool JSONArray::Remove(u32_t index)
{
   if (index < pValList->GetCount()) {
      pValList->RemoveAt(static_cast<int>(index));
      return true;
   }   
   return false;
}

} // end of namespace json

} // end of namespace cppflib
